using System;
using System.Collections.Generic;
using System.IO;
using AndyPike.Experiments.DB4O.Tests.Entities;
using Db4objects.Db4o;
using NUnit.Framework;
using Db4objects.Db4o.Linq;
using System.Linq;
using NUnit.Framework.SyntaxHelpers;

namespace AndyPike.Experiments.DB4O.Tests
{
    [TestFixture]
    public class When_using_db4o_for_simple_crud
    {
        private string path;

        [SetUp]
        public void SetUp()
        {
            path = GetType().Assembly.CodeBase.Replace("file:///", "").Replace("/", @"\");
            path = Path.GetDirectoryName(path);
            path = Path.Combine(path, "basics.db4o");
        }

        [Test]
        public void Should_open_and_close_a_database_connection()
        {
            using(IObjectContainer db = Db4oFactory.OpenFile(path))
            {
            }
        }

        [Test]
        public void Should_store_a_simple_object()
        {
            using (IObjectContainer db = Db4oFactory.OpenFile(path))
            {
                var account = new Account(Guid.NewGuid(), "andy@andypike.com", "Andy", "Pike", 31);
                db.Store(account);
            }
        }

        [Test]
        public void Should_retrieve_a_simple_object_using_linq()
        {
            using (IObjectContainer db = Db4oFactory.OpenFile(path))
            {
                IEnumerable<Account> accounts = from Account a in db
                                                where a.FirstName.Equals("Andy")
                                                select a;

                Assert.That(accounts.Count(), Is.GreaterThan(0));
            }
        }

        [Test]
        public void Should_retrieve_a_simple_object_using_linq_as_queryable()
        {
            using (IObjectContainer db = Db4oFactory.OpenFile(path))
            {
                ICollection<Account> accounts = db.Cast<Account>().AsQueryable().Where(a => a.FirstName.Equals("Andy")).ToList();

                Assert.That(accounts.Count, Is.GreaterThan(0));
            }
        }

        [Test]
        public void Should_update_a_simple_object()
        {
            Guid id = Guid.NewGuid();

            using (IObjectContainer db = Db4oFactory.OpenFile(path))
            {
                var account = new Account(id, "andy@andypike.com", "Andy", "Pike", 31);
                db.Store(account);

                account.FirstName = "Amber";
                account.Age = 3;

                db.Store(account);

                IList<Account> accounts = db.Cast<Account>().AsQueryable().Where(a => a.Id.Equals(id)).ToList();

                Assert.That(accounts.Count, Is.EqualTo(1));
                Assert.That(accounts[0].Id, Is.EqualTo(id));
                Assert.That(accounts[0].FirstName, Is.EqualTo("Amber"));
                Assert.That(accounts[0].Age, Is.EqualTo(3));
            }
        }

        [Test]
        public void Should_delete_a_simple_object()
        {
            Guid id = Guid.NewGuid();

            using (IObjectContainer db = Db4oFactory.OpenFile(path))
            {
                var account = new Account(id, "andy@andypike.com", "Andy", "Pike", 31);
                db.Store(account);

                ICollection<Account> before = db.Cast<Account>().ToList();
                int beforeCount = before.Count;

                db.Delete(account);

                ICollection<Account> after = db.Cast<Account>().ToList();
                int afterCount = after.Count;

                ICollection<Account> matches = db.Cast<Account>().AsQueryable().Where(a => a.Id.Equals(id)).ToList();

                Assert.That(afterCount, Is.EqualTo(beforeCount - 1));
                Assert.That(matches.Count, Is.EqualTo(0));
            }
        }
    }
}